<?php
declare(strict_types=1);

namespace App\Service;

use App\Constants\StrStatus;
use App\Model\Dao\BankInfoDao;
use App\Model\Dao\ChannelInfoDao;
use App\Model\Dao\TradeOrderBaseDao;
use App\Model\Dao\TradeOrderDetailDao;
use App\Model\Dao\TradeOrderRefundDao;
use App\Model\Enum\BankRefundStatusEnum;
use App\Model\Enum\StatusEnum;
use App\Utils\CustomUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\TradeOrderRefundBankDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Arr;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;


class TradeOrderRefundBankService {
    /**
     * @Inject()
     * @var TradeOrderRefundBankDao
     */
    private $TradeOrderRefundBankDao;

    /**
     * @Inject()
     * @var TradeOrderRefundDao
     */
    private $TradeOrderRefundDao;

    /**
     * @Inject()
     * @var TradeOrderDetailDao
     */
    private $TradeOrderDetailDao;

    /**
     * @Inject()
     * @var TradeOrderBaseDao
     */
    private $TradeOrderBaseDao;

    /**
     * @Inject()
     * @var ChannelInfoDao
     */
    private $ChannelInfoDao;

    /**
     * @Inject()
     * @var BankInfoDao
     */
    private $BankInfoDao;

    /**
     * @Inject()
     * @var CommonBankService
     */
    private $CommonBankService;



    /**
     * @param $param
     *
     * @return array
     * 失败重试
     */
    public function tryAgain ($param) {
        $result = $this->TradeOrderRefundBankDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        if (!$param['isSuperRole']) {
            if (!in_array($result['mchId'], $param['mchIdList'])) {
                throw new XZXValidationException("没有权限做此项操作");
            }
        }

        if ($result['bankRefundStatus'] == 1) {
            throw new XZXValidationException("已退款成功，请勿重复操作！");
        }
        // todo: 失败重试，请求网关
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), "");
    }

    public function add ($param) {
        // TODO: Implement add() method.
        //$data            =  [
        //    'name'       => $param['name'],
        //    'desciption' => $param['desciption'],
        //
        //];
        $data = $param;
        CustomUtils::xzxDebug($data);

        try {
            $this->TradeOrderRefundBankDao->insert($data);
        } catch (\Throwable $th) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::ADD_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), CustomUtils::xzxEmptyObject());
    }

    public function list (array $param) {

        $limit = $param['limit'];
        $page  = $param['page'];

        $total = $this->TradeOrderRefundBankDao->getCount($param);
        $list  = $this->TradeOrderRefundBankDao->getList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['strBankRefundStatus'] = BankRefundStatusEnum::getLabel($v['bankRefundStatus']);
            $list[$k]                 = $v;
        }

        $data = [
            'total' => $total,
            'list'  => $list,
        ];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $data);
    }

    public function doBankRefundAndAccountTrans ($refundList) {

        $result = [];

        foreach ($refundList as $item) {

            $returnMsg = 'success';

            // 退款单
            $refund = $this->TradeOrderRefundDao->get($item['refundId']);

            // 退款记录
            $refundBank = $this->TradeOrderRefundBankDao->get($item['id']);

            // 订单详情
            $detail = $this->TradeOrderDetailDao->get($refund['orderId']);

            $base = $this->TradeOrderBaseDao->getWhere(['tradeNo' => $detail['tradeNo']]);

            $channel = $this->ChannelInfoDao->get($detail['channelId']);

            $bank = $this->BankInfoDao->get($channel['bankId']);

            $channelParam    = json_decode($channel['params'], true);
            $bankRefundParam = [];
            foreach ($channelParam as $k => $v) {
                $bankRefundParam[$k] = $v;
            }

            // 拼上银行参数
            $bankRefundParam['bankHost']      = $bank['host'];
            $bankRefundParam['bankPort']      = $bank['port'];
            $bankRefundParam['bankProxyHost'] = $bank['proxyHost'];
            $bankRefundParam['bankProxyPort'] = $bank['proxyPort'];

            $bankRefundParam['channel']       = $bank['type'];
            $bankRefundParam['tradeNo']       = $detail['tradeNo'];
            $bankRefundParam['tradeNewNo']    = $refund['tradeNewNo'];
            $bankRefundParam['relNo']         = $detail['relNo'];
            $bankRefundParam['currency']      = $refund['transCurrency'];
            $bankRefundParam['refundAmount']  = $refund['transAmount'];
            $bankRefundParam['bankTransTime'] = date('Y-m-d H:i:s', $detail['channelTransTime']);
            $bankRefundParam['transReason']   = $refund['transReason'];

            $this->_extraBankRefundParam($bankRefundParam, $detail, $base, $refund, $refundBank, $bank, $channel);

            $bankRefundResult = $this->CommonBankService->doRefund($bankRefundParam);

            if (CustomUtils::isSuccess($bankRefundResult)) {
                $this->TradeOrderRefundDao->update($refund['id'], [
                    'bankRefundStatus' => 1,
                    'bankRefundTimes'  => Db::raw("`bankRefundTimes` + 1"),
                    'refundByApi'      => 1,
                ]);

                $this->TradeOrderRefundBankDao->update($refundBank['id'], [
                    'bankOrgRefundStatus' => $bankRefundResult['code'],
                    'bankRefundStatus'    => 1,
                    'bankRefundTime'      => time(),
                ]);
            }
            else {

                $this->TradeOrderRefundDao->update($refund['id'], [
                    'bankRefundStatus' => 2,
                    'bankRefundTimes'  => Db::raw("`bankRefundTimes` + 1"),
                    'refundByApi'      => 1,
                ]);

                $this->TradeOrderRefundBankDao->update($refundBank['id'], [
                    'bankOrgRefundStatus' => $bankRefundResult['code'],
                    'bankRefundStatus'    => 2,
                    'bankRefundTime'      => time(),
                ]);

                $returnMsg = "退款单号：{$refund['tradeNo']} 退款操作失败，原因：{$bankRefundResult['message']};";
            }

            $result[$item['id']] = CustomUtils::xeServiceReturnData($bankRefundResult['code'], $returnMsg, $item);
        }

        return CustomUtils::buildSuccess($result);
    }

    protected function _extraBankRefundParam (&$bankRefundParam, $order, $base, $refund, $bankRefund, $bank, $channel) {

    }

    public function doAdd ($params) {

        if (Arr::isAssoc($params)) {
            // 关联数组
            return $this->doAdd([$params]);
        }

        $updateList = $params;

        foreach ($updateList as $k => $item) {

            $item = [
                'id'                  => CustomUtils::createUUID(),
                'refundId'            => $item['refundId'],
                'orderId'             => $item['orderId'],
                'tradeNo'             => $item['tradeNo'],
                'relNo'               => $item['relNo'],
                'mchId'               => $item['mchId'],
                'mchNo'               => $item['mchNo'],
                'bankId'              => $item['bankId'],
                'channelId'           => $item['channelId'],
                'channelName'         => $item['channelName'],
                'bankRefundAmount'    => $item['bankRefundAmount'],
                'bankRefundCurrency'  => $item['bankRefundCurrency'],
                'bankRefundNo'        => CustomUtils::createTradeNo('refund'),
                'bankOrgRefundStatus' => '',
                'bankRefundStatus'    => 0,
                'bankRefundTime'      => 0,
                'status'              => StatusEnum::ON,
                'createTime'          => time(),
                'createBy'            => $item['createBy'],
            ];

            $updateList[$k] = $item;
        }

        $this->TradeOrderRefundBankDao->insert($updateList);

        return $updateList;

    }
}
